--[[ 虫姬1,简单的显示自机,并降低UI位置,否则存档读档的UI太高

  By setycyas @2025-09-20
]]

--防止重运行,需用用_G,用重复require不行,因为F4重启可能会把脚本加载到全新模块与原来的不共通
if (_G.game) then
  print('script already loaded!')
  return
end

local myMame = require('MyMame')
local mySTG = require('MySTG')

-- 这里设定基本参数
GAME = {
  -- 游戏名,防重加载用
  NAME = "mushisam_autoboot",
  -- 分辨率
  X_RESOLUTION = 240,
  Y_RESOLUTION = 320,
  -- 横坐标纵坐标内存地址
  X_ADDR_LOW = 0x0c1ed391,
  X_ADDR_HIGH = 0x0c1ed390,
  Y_ADDR_LOW = 0x0c1ed395,
  Y_ADDR_HIGH = 0x0c1ed394,
  
  -- 如果仅用read_u16读取坐标和计算,就设定为true
  USE_U16 = true,
  -- 十字方块的边框颜色和中心颜色
  CROSS_BORDER_COLOR = 0x99ff00ff,
  CROSS_COLOR =  0x660000ff,
  -- 十字线颜色,易被自机子弹遮盖,建议设为子弹的反色
  CROSS_LINE_WIDTH = 0.002, --十字线宽度
  CROSS_LINE_COLOR = 0x88000000,
  -- mame api用的对象
  mem = manager.machine.devices[':maincpu'].spaces['program'],
  container = manager.machine.screens[":screen"].container,
  ui_container = manager.machine.render.ui_container,
}
-- 更新模块设置
myMame.gameName = GAME.NAME
myMame.screenIndex = ':screen'

-- 刷新设备,成功获取设备返回true,否返回false
function GAME.refreshDevices()
  GAME.mem = manager.machine.devices[':maincpu'].spaces['program']
  GAME.container = manager.machine.screens[":screen"].container
  GAME.ui_container = manager.machine.render.ui_container
  
  if (GAME.mem and GAME.container and GAME.ui_container) then
    return true
  else
    return false
  end
end

-- 坐标变换,从内存坐标变为屏幕显示位置,返回0.0-1.0的浮点数,
function GAME.getX_u16()
  local x
  x = GAME.mem:read_u16(GAME.X_ADDR_HIGH)
  result = x/GAME.X_RESOLUTION
  
  return result
end
function GAME.getY_u16()
  local y
  y = GAME.mem:read_u16(GAME.Y_ADDR_HIGH)
  result = y/GAME.Y_RESOLUTION
  
  return result
end
function GAME.getX_u8()
  local xlow, result
  xlow = GAME.mem:read_u8(GAME.X_ADDR_LOW)
  result = xlow/GAME.X_RESOLUTION
  
  return result
end
function GAME.getY_u8()
  local ylow, yhigh, result
  yhigh = GAME.mem:read_u8(GAME.Y_ADDR_HIGH)
  ylow = GAME.mem:read_u8(GAME.Y_ADDR_LOW)
  result = (yhigh*256+ylow)/GAME.Y_RESOLUTION
  
  return result
end

-- 数据显示,指定位置和颜色,然后是可变的多个显示数据
function GAME.showInfo(position, color, ...)
  local count = select("#", ...)
  
  for i = 1, count do
    local arg = select(i, ...)
    GAME.ui_container:draw_text(position, 1.01-0.05*i, arg, color, 0xFF839496)
  end
  
end

-- 监视数据显示
function GAME.check()
  local xlow, ylow, xhigh, yhigh --内存数据
  yhigh = GAME.mem:read_u8(GAME.Y_ADDR_HIGH)
  xlow = GAME.mem:read_u8(GAME.X_ADDR_LOW)
  ylow = GAME.mem:read_u8(GAME.Y_ADDR_LOW)
  xhigh = GAME.mem:read_u8(GAME.X_ADDR_HIGH)
  -- 显示当前火力等级
  GAME.showInfo(0.05, 0xFF000000, 
    string.format(" XH=%d XL=%d YH=%d YL=%d", xhigh, xlow, yhigh, ylow)
  )
end

-- 显示十字线
function GAME.showCrossLine(xfloat, yfloat)

  -- 横线
  GAME.container:draw_box(
    0.0, xfloat-GAME.CROSS_LINE_WIDTH, 
    1.0, xfloat+GAME.CROSS_LINE_WIDTH, 
    GAME.CROSS_LINE_COLOR, GAME.CROSS_LINE_COLOR
  )
  -- 竖线
  GAME.container:draw_box(
    yfloat-GAME.CROSS_LINE_WIDTH, 0.0,
    yfloat+GAME.CROSS_LINE_WIDTH, 1.0,
    GAME.CROSS_LINE_COLOR, GAME.CROSS_LINE_COLOR
  )
  
end

--[[ **************************
  主函数,绑定后每一帧执行一次该函数
]]
function GAME.Main()
  --local xhigh, xlow, yhigh, ylow, shotLv, laserLv --内存数据
  local xfloat, yfloat -- 最终浮点数坐标

  -- 刷新设备,并判断当前帧能否操作
  if (not GAME.refreshDevices()) then
    return
  end

  -- 获取自己屏幕坐标
  if GAME.USE_U16 then
    xfloat = GAME.getX_u16()
    yfloat = GAME.getY_u16()
  else
    xfloat = GAME.getX_u8()
    yfloat = GAME.getY_u8()
  end
  
  -- 数据监视
  --GAME.check()
  -- 显示角色中心辅助线
  if (xfloat > 0.0) and (yfloat > 0.0) then
    -- 十字线
    GAME.showCrossLine(xfloat, yfloat)
  end
  
end

--[[运行]]

-- 刷新api接口
GAME.refreshDevices()
-- 导出到全局变量
_G.game = GAME
-- 绑定每一帧执行的函数,测试时绑定到debug
--myMame.debugRunPerFrame(GAME.Main, 'mushisam')
myMame.runPerFrame(GAME.Main, 'mushisam')
mySTG.ui_handle()

return GAME
